home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / hoster.c < prev    next >
C/C++ Source or Header  |  1997-08-08  |  18KB  |  776 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: hoster.c,v 1.7 1997/06/25 22:08:46 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    hoster.c
  35.  *
  36.  *    Slave pvmd starter.
  37.  *
  38. $Log: hoster.c,v $
  39.  * Revision 1.7  1997/06/25  22:08:46  pvmsrc
  40.  * Markus adds his frigging name to the author list of
  41.  *     every file he ever looked at...
  42.  *
  43.  * Revision 1.6  1997/04/21  14:58:22  pvmsrc
  44.  * Changed #ifdefs that checked IMA_RS6K,IMA_SP2MPI & IMA_AIX46K
  45.  *     to see if select.h was needed into single define NEEDSSELECTH.
  46.  *     New archs need to set this in conf/
  47.  *
  48.  * Revision 1.5  1997/01/28  19:26:19  pvmsrc
  49.  * New Copyright Notice & Authors.
  50.  *
  51.  * Revision 1.4  1996/10/25  13:57:19  pvmsrc
  52.  * Replaced old #includes for protocol headers:
  53.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  54.  * With #include of new combined header:
  55.  *     - <pvmproto.h>
  56.  *
  57.  * Revision 1.3  1996/10/24  21:04:47  pvmsrc
  58.  * Moved #include of "global.h" down below other headers:
  59.  *     - need to have all of the structures / types declared before
  60.  *         the globals can be declared...
  61.  *
  62.  * Revision 1.2  1996/09/23  23:48:01  pvmsrc
  63.  * Initial Creation - original hoster.c.
  64.  *
  65.  * Revision 1.1  1996/09/23  23:44:09  pvmsrc
  66.  * Initial revision
  67.  *
  68.  * Revision 1.17  1995/11/02  16:36:14  manchek
  69.  * added NEEDSENDIAN switch
  70.  *
  71.  * Revision 1.16  1995/07/28  16:41:01  manchek
  72.  * wrap HASERRORVARS around errno declarations
  73.  *
  74.  * Revision 1.15  1995/07/28  16:04:06  manchek
  75.  * switch endian includes on flag, not arch name
  76.  *
  77.  * Revision 1.14  1995/07/11  18:55:33  manchek
  78.  * moved printing of PVMSOCK in master_config to main
  79.  *
  80.  * Revision 1.13  1995/07/03  19:06:54  manchek
  81.  * removed POWER4 ifdefs
  82.  *
  83.  * Revision 1.12  1995/05/30  17:53:08  manchek
  84.  * Added ifdefs and small changes for SP2MPI arch
  85.  *
  86.  * Revision 1.11  1995/05/17  16:53:03  manchek
  87.  * use FDSETISINT in select
  88.  *
  89.  * Revision 1.10  1995/02/06  21:35:59  manchek
  90.  * host table mtu set from ourudpmtu instead of UDPMAXLEN
  91.  *
  92.  * Revision 1.9  1994/10/15  19:31:31  manchek
  93.  * fixed typo in log message
  94.  *
  95.  * Revision 1.8  1994/06/04  21:45:24  manchek
  96.  * added unix domain sockets.
  97.  * ripped out old (serial) startup code
  98.  *
  99.  * Revision 1.7  1994/06/03  20:38:27  manchek
  100.  * version 3.3.0
  101.  *
  102.  * Revision 1.6  1993/11/30  19:54:41  manchek
  103.  * check the default entry in filehosts when adding new hosts
  104.  *
  105.  * Revision 1.5  1993/11/30  16:46:10  manchek
  106.  * pass whole remote command as a single arg to rsh
  107.  *
  108.  * Revision 1.4  1993/11/30  15:54:37  manchek
  109.  * master pvmd once again doesn't close fds 0..2 -
  110.  * this broke rexec startup
  111.  *
  112.  * Revision 1.3  1993/10/25  20:53:51  manchek
  113.  * fixed a few typos in error log messages.
  114.  * added code to close all fds and reopen 0..2 as /dev/null
  115.  *
  116.  * Revision 1.2  1993/10/04  20:30:30  manchek
  117.  * mksocks() now uses pvmdsockfile() instead of TDSOCKNAME
  118.  *
  119.  * Revision 1.1  1993/08/30  23:26:51  manchek
  120.  * Initial revision
  121.  *
  122.  */
  123.  
  124. #ifdef NEEDMENDIAN
  125. #include <machine/endian.h>
  126. #endif
  127. #ifdef NEEDENDIAN
  128. #include <endian.h>
  129. #endif
  130. #ifdef NEEDSENDIAN
  131. #include <sys/endian.h>
  132. #endif
  133. #include <rpc/types.h>
  134. #include <rpc/xdr.h>
  135. #ifdef IMA_TITN
  136. #include <bsd/sys/types.h>
  137. #else
  138. #include <sys/types.h>
  139. #endif
  140. #include <sys/time.h>
  141. #ifdef NEEDSSELECTH
  142. #include <sys/select.h>
  143. #endif
  144. #include <sys/socket.h>
  145. #include <netinet/in.h>
  146. #include <fcntl.h>
  147. #include <stdio.h>
  148. #include <errno.h>
  149. #include <ctype.h>
  150. #ifdef    SYSVSTR
  151. #include <string.h>
  152. #define    CINDEX(s,c)    strchr(s,c)
  153. #else
  154. #include <strings.h>
  155. #define    CINDEX(s,c)    index(s,c)
  156. #endif
  157. #include <netdb.h>
  158.  
  159. #include <pvm3.h>
  160. #include <pvmproto.h>
  161. #include "pvmalloc.h"
  162. #include "pmsg.h"
  163. #include "host.h"
  164. #include "listmac.h"
  165. #include "tvdefs.h"
  166. #include "bfunc.h"
  167. #include "global.h"
  168.  
  169. #ifndef    RSHCOMMAND
  170. #define    RSHCOMMAND    "/usr/ucb/rsh"
  171. #endif
  172.  
  173. #ifndef    RSHTIMEOUT
  174. #define    RSHTIMEOUT    60
  175. #endif
  176.  
  177. #ifndef    RSHNPLL
  178. #define    RSHNPLL    5
  179. #endif
  180.  
  181. #ifndef    max
  182. #define    max(a,b)    ((a)>(b)?(a):(b))
  183. #endif
  184.  
  185. #ifndef    min
  186. #define    min(a,b)    ((a)<(b)?(a):(b))
  187. #endif
  188.  
  189.  
  190. struct hst {
  191.     int h_tid;
  192.     char *h_name;
  193.     char *h_login;
  194.     char *h_sopts;
  195.     int h_flag;
  196. #define    HST_PASSWORD    1        /* ask for a password */
  197. #define    HST_MANUAL        2        /* do manual startup */
  198.     char *h_cmd;
  199.     char *h_result;
  200. };
  201.  
  202. struct slot {
  203.     struct slot *s_link, *s_rlink;        /* free/active list */
  204.     struct hst *s_hst;                    /* host table entry */
  205.     struct timeval s_bail;                /* timeout time */
  206.     int s_rfd, s_wfd, s_efd;            /* slave stdin/out/err */
  207.     char s_buf[256];                    /* stdout from host */
  208.     char s_ebuf[256];                    /* stderr from host */
  209.     int s_len;                            /* length of s_buf */
  210.     int s_elen;                            /* length of s_ebuf */
  211. };
  212.  
  213.  
  214. /***************
  215.  **  Globals  **
  216.  **           **
  217.  ***************/
  218.  
  219. #ifndef HASERRORVARS
  220. extern int errno;
  221. #endif
  222.  
  223. extern void pvmbailout();
  224.  
  225. extern int pvmdebmask;                /* from pvmd.c */
  226. extern char *username;                /* from pvmd.c */
  227.  
  228.  
  229. /***************
  230.  **  Private  **
  231.  **           **
  232.  ***************/
  233.  
  234. static struct slot slots[RSHNPLL+2];    /* state var/context for each slot */
  235. static struct slot *slfree = 0;            /* free list of slots */
  236.  
  237.  
  238. int
  239. hoster(mp)
  240.     struct pmsg *mp;
  241. {
  242.     struct pmsg *mp2;
  243.     int num;
  244.     int i;
  245.     struct hst **hostlist;
  246.     struct hst *hp;
  247.     char *p;
  248.  
  249.     /*
  250.     * unpack the startup message
  251.     */
  252.  
  253.     upkint(mp, &num);
  254.     if (pvmdebmask & PDMSTARTUP) {
  255.         pvmlogprintf("hoster() %d to start\n", num);
  256.     }
  257.     if (num > 0) {
  258.         hostlist = TALLOC(num, struct hst *, "hsts");
  259.         for (i = 0; i < num; i++) {
  260.             hp = TALLOC(1, struct hst, "hst");
  261.             hostlist[i] = hp;
  262.             hp->h_flag = 0;
  263.             hp->h_result = 0;
  264.             if (upkint(mp, &hp->h_tid)
  265.             || upkstralloc(mp, &hp->h_sopts)
  266.             || upkstralloc(mp, &hp->h_login)
  267.             || upkstralloc(mp, &hp->h_cmd)) {
  268.                 pvmlogerror("hoster() bad message format\n");
  269.                 pvmbailout(0);
  270.             }
  271.             if (pvmdebmask & PDMSTARTUP) {
  272.                 pvmlogprintf("%d. t%x %s so=\"%s\"\n", i,
  273.                         hp->h_tid,
  274.                         hp->h_login,
  275.                         hp->h_sopts);
  276.             }
  277.             if (p = CINDEX(hp->h_login, '@')) {
  278.                 hp->h_name = STRALLOC(p + 1);
  279.                 *p = 0;
  280.                 p = STRALLOC(hp->h_login);
  281.                 PVM_FREE(hp->h_login);
  282.                 hp->h_login = p;
  283.  
  284.             } else {
  285.                 hp->h_name = hp->h_login;
  286.                 hp->h_login = 0;
  287.             }
  288.             if (!strcmp(hp->h_sopts, "pw"))
  289.                 hp->h_flag |= HST_PASSWORD;
  290.             if (!strcmp(hp->h_sopts, "ms"))
  291.                 hp->h_flag |= HST_MANUAL;
  292.         }
  293.     }
  294.  
  295.     /*
  296.     * do it
  297.     */
  298.  
  299.     pl_startup(num, hostlist);
  300.  
  301.     /*
  302.     * send results back to pvmd
  303.     */
  304.  
  305.     mp2 = mesg_new(0);
  306.     mp2->m_dst = mp->m_src;
  307.     mp2->m_tag = DM_STARTACK;
  308.     mp2->m_wid = mp->m_wid;
  309.     pkint(mp2, num);
  310.     for (i = 0; i < num; i++) {
  311.         pkint(mp2, hostlist[i]->h_tid);
  312.         pkstr(mp2, hostlist[i]->h_result
  313.                 ? hostlist[i]->h_result : "PvmDSysErr");
  314.     }
  315.     if (pvmdebmask & PDMSTARTUP)
  316.         pvmlogerror("hoster() pvmd' sending back host table\n");
  317.     sendmessage(mp2);
  318.     work();        /* no return */
  319.     return 0;    /* not reached */
  320. }
  321.  
  322.  
  323. char *
  324. makevis(dst, src)
  325.     char *dst;
  326.     char *src;
  327. {
  328.     char c;
  329.  
  330.     while (c = *src++ & 0x7f) {
  331.         if (isprint(c))
  332.             *dst++ = c;
  333.  
  334.         else {
  335.             *dst++ = '^';
  336.             *dst++ = (c + '@') & 0x7f;
  337.         }
  338.     }
  339.     *dst = 0;
  340.     return dst;
  341. }
  342.  
  343.  
  344. close_slot(sp)
  345.     struct slot *sp;
  346. {
  347.     if (sp->s_wfd != -1)
  348.         (void)close(sp->s_wfd);
  349.     if (sp->s_rfd != -1)
  350.         (void)close(sp->s_rfd);
  351.     if (sp->s_efd != -1)
  352.         (void)close(sp->s_efd);
  353.     LISTDELETE(sp, s_link, s_rlink);
  354.     LISTPUTBEFORE(slfree, sp, s_link, s_rlink);
  355.     return 0;
  356. }
  357.  
  358.  
  359. pl_startup(num, hostlist)
  360.     int num;
  361.     struct hst **hostlist;
  362. {
  363.     int nxth = 0;                        /* next host in list to start */
  364.     struct slot *slact = 0;                /* active list of slots */
  365.     struct hst *hp;
  366.     struct slot *sp, *sp2;
  367.     struct timeval tnow;
  368.     struct timeval tout;
  369. #ifdef IMA_OS2
  370.         fd_set rfds;  /* emx headers */
  371. #else   
  372.     struct fd_set rfds;
  373. #endif
  374.     int nfds;
  375.     int i;
  376.     int n;
  377.     char *p;
  378.  
  379.     /* init slot free list */
  380.  
  381.     slfree = &slots[RSHNPLL+1];
  382.     slfree->s_link = slfree->s_rlink = slfree;
  383.     slact = &slots[RSHNPLL];
  384.     slact->s_link = slact->s_rlink = slact;
  385.     for (i = RSHNPLL; i-- > 0; ) {
  386.         LISTPUTAFTER(slfree, &slots[i], s_link, s_rlink);
  387.     }
  388.  
  389.     /*
  390.     * keep at this until all hosts in table are completed
  391.     */
  392.  
  393.     for (; ; ) {
  394.  
  395.         /*
  396.         * if empty slots, start on new hosts
  397.         */
  398.  
  399.         for (; ; ) {
  400.  
  401.             /* find a host for slot */
  402.  
  403.             if (slfree->s_link != slfree && nxth < num)
  404.                 hp = hostlist[nxth++];
  405.             else
  406.                 break;
  407.  
  408.             sp = slfree->s_link;
  409.             LISTDELETE(sp, s_link, s_rlink);
  410.             sp->s_hst = hp;
  411.             sp->s_len = 0;
  412.             sp->s_elen = 0;
  413.             if (pvmdebmask & PDMSTARTUP) {
  414.                 pvmlogprintf("pl_startup() trying %s\n", hp->h_name);
  415.             }
  416.             phase1(sp);
  417.             if (hp->h_result) {
  418.                 /* error or fully started (manual startup) */
  419.  
  420.                 LISTPUTBEFORE(slfree, sp, s_link, s_rlink);
  421.  
  422.             } else {
  423.                 /* partially started */
  424.  
  425.                 LISTPUTBEFORE(slact, sp, s_link, s_rlink);
  426.                 pvmgetclock(&sp->s_bail);
  427.                 tout.tv_sec = RSHTIMEOUT;
  428.                 tout.tv_usec = 0;
  429.                 TVXADDY(&sp->s_bail, &sp->s_bail, &tout);
  430.             }
  431.         }
  432.  
  433.         /* if no hosts in progress, we are finished */
  434.  
  435.         if (slact->s_link == slact)
  436.             break;
  437.  
  438.         /*
  439.         * until next timeout, get output from any slot
  440.         */
  441.  
  442.         FD_ZERO(&rfds);
  443.         nfds = 0;
  444.         TVCLEAR(&tout);
  445.         pvmgetclock(&tnow);
  446.         for (sp = slact->s_link; sp != slact; sp = sp->s_link) {
  447.             if (TVXLTY(&sp->s_bail, &tnow)) {
  448.                 pvmlogprintf("pl_startup() giving up on host %s after %d secs\n",
  449.                         sp->s_hst->h_name, RSHTIMEOUT);
  450.                 sp->s_hst->h_result = STRALLOC("PvmCantStart");
  451.                 sp2 = sp->s_rlink;
  452.                 close_slot(sp);
  453.                 sp = sp2;
  454.                 continue;
  455.             }
  456.  
  457.             if (!TVISSET(&tout) || TVXLTY(&sp->s_bail, &tout))
  458.                 tout = sp->s_bail;
  459.             if (sp->s_rfd >= 0)
  460.                 FD_SET(sp->s_rfd, &rfds);
  461.             if (sp->s_rfd > nfds)
  462.                 nfds = sp->s_rfd;
  463.             if (sp->s_efd >= 0)
  464.                 FD_SET(sp->s_efd, &rfds);
  465.             if (sp->s_efd > nfds)
  466.                 nfds = sp->s_efd;
  467.         }
  468.  
  469.         if (slact->s_link == slact)
  470.             break;
  471.  
  472.         nfds++;
  473.  
  474.         if (TVXLTY(&tnow, &tout)) {
  475.             TVXSUBY(&tout, &tout, &tnow);
  476.         } else {
  477.             TVCLEAR(&tout);
  478.         }
  479.         if (pvmdebmask & PDMSTARTUP) {
  480.             pvmlogprintf("pl_startup() select timeout is %d.%06d\n",
  481.                     tout.tv_sec, tout.tv_usec);
  482.         }
  483.         if ((n = select(nfds,
  484. #ifdef    FDSETISINT
  485.                 (int *)&rfds, (int *)0, (int *)0,
  486. #else
  487.                 &rfds, (fd_set *)0, (fd_set *)0,
  488. #endif
  489.                 &tout)) == -1) {
  490.             if (errno != EINTR) {
  491.                 pvmlogperror("pl_startup() select");
  492.                 pvmbailout(0);
  493.             }
  494.         }
  495.         if (pvmdebmask & PDMSTARTUP) {
  496.             pvmlogprintf("pl_startup() select returns %d\n", n);
  497.         }
  498.         if (n < 1) {
  499.             if (n == -1 && errno != EINTR) {
  500.                 pvmlogperror("pl_startup() select");
  501.                 pvmbailout(0);    /* XXX this is too harsh */
  502.             }
  503.             continue;
  504.         }
  505.  
  506.         /*
  507.         * check for response on stdout or stderr of any slave.
  508.         */
  509.  
  510.         for (sp = slact->s_link; sp != slact; sp = sp->s_link) {
  511.  
  512.             /*
  513.             * stderr ready.  log output with remote's host name.
  514.             */
  515.             if (sp->s_efd >= 0 && FD_ISSET(sp->s_efd, &rfds)) {
  516.                 n = read(sp->s_efd, sp->s_ebuf + sp->s_elen,
  517.                         sizeof(sp->s_ebuf) - sp->s_elen - 1);
  518.                 if (n > 0) {
  519.                     sp->s_elen += n;
  520.                     sp->s_ebuf[sp->s_elen] = 0;
  521.                     while (p = CINDEX(sp->s_ebuf, '\n')) {
  522.                         *p = 0;
  523.                         pvmlogprintf("stderr@%s: %s\n",
  524.                                 sp->s_hst->h_name, sp->s_ebuf);
  525.                         p++;
  526.                         sp->s_elen -= p - sp->s_ebuf;
  527.                         if (sp->s_elen > 0) {
  528.                             bcopy(p, sp->s_ebuf, sp->s_elen);
  529.                             sp->s_ebuf[sp->s_elen] = 0;
  530.                         }
  531.                     }
  532.                     if (sp->s_elen == sizeof(sp->s_ebuf) - 1) {
  533.                         pvmlogprintf("stderr@%s: %s\n",
  534.                                 sp->s_hst->h_name, sp->s_ebuf);
  535.                         sp->s_elen = 0;
  536.                     }
  537.  
  538.                 } else {
  539.                     if (sp->s_elen > 0) {
  540.                         pvmlogprintf("stderr@%s: %s\n",
  541.                                 sp->s_hst->h_name, sp->s_ebuf);
  542.                         sp->s_elen = 0;
  543.                     }
  544.                     (void)close(sp->s_efd);
  545.                     sp->s_efd = -1;
  546.                 }
  547.             }
  548.  
  549.             /*
  550.             * stdout ready.
  551.             * look for a complete line starting with "ddpro".
  552.             */
  553.             if (sp->s_rfd >= 0 && FD_ISSET(sp->s_rfd, &rfds)) {
  554.                 n = read(sp->s_rfd, sp->s_buf + sp->s_len,
  555.                         sizeof(sp->s_buf) - sp->s_len - 1);
  556.                 if (n > 0) {
  557.                     sp->s_len += n;
  558.                     sp->s_buf[sp->s_len] = 0;
  559.                     while (p = CINDEX(sp->s_buf, '\n')) {
  560.                         *p = 0;
  561.                         if (!strncmp(sp->s_buf, "ddpro", 5)) {
  562.                             if (pvmdebmask & PDMSTARTUP) {
  563.                                 pvmlogprintf("stdout@%s: %s\n",
  564.                                         sp->s_hst->h_name, sp->s_buf);
  565.                             }
  566.                             sp->s_hst->h_result = STRALLOC(sp->s_buf);
  567.                             break;
  568.  
  569.                         } else {
  570.                             pvmlogprintf("stdout@%s: %s\n",
  571.                                     sp->s_hst->h_name, sp->s_buf);
  572.                             p++;
  573.                             sp->s_len -= p - sp->s_buf;
  574.                             if (sp->s_len > 0) {
  575.                                 bcopy(p, sp->s_buf, sp->s_len);
  576.                                 sp->s_buf[sp->s_len] = 0;
  577.                             }
  578.                         }
  579.                     }
  580.                     if (sp->s_len == sizeof(sp->s_buf) - 1) {
  581.                         pvmlogprintf("stdout@%s: %s\n",
  582.                                 sp->s_hst->h_name, sp->s_buf);
  583.                         sp->s_len = 0;
  584.                     }
  585.  
  586.                 } else {
  587.                     if (sp->s_len > 0) {
  588.                         pvmlogprintf("stdout@%s: %s\n",
  589.                                 sp->s_hst->h_name, sp->s_buf);
  590.                         sp->s_len = 0;
  591.                     }
  592.                     if (n) {
  593.                         pvmlogprintf("stdout@%s",
  594.                                 sp->s_hst->h_name);
  595.                     } else {
  596.                         pvmlogprintf("stdout@%s: EOF\n",
  597.                                 sp->s_hst->h_name);
  598.                     }
  599.                     sp->s_hst->h_result = STRALLOC("PvmCantStart");
  600.                     if (sp->s_elen > 0) {
  601.                         pvmlogprintf("stderr@%s: %s\n",
  602.                                 sp->s_hst->h_name, sp->s_ebuf);
  603.                         sp->s_elen = 0;
  604.                     }
  605.                 }
  606.                 if (sp->s_hst->h_result) {
  607.                     sp2 = sp->s_rlink;
  608.                     close_slot(sp);
  609.                     sp = sp2;
  610.                     continue;
  611.                 }
  612.             }
  613.         }
  614.     }
  615.     return 0;
  616. }
  617.  
  618.  
  619. phase1(sp)
  620.     struct slot *sp;
  621. {
  622.     struct hst *hp;
  623.     char *hn;
  624.     char *av[16];            /* for rsh args */
  625.     int ac;
  626.     char buf[512];
  627.     int pid = -1;            /* pid of rsh */
  628.     char *p;
  629.  
  630. #ifndef NOREXEC
  631.     struct servent *se;
  632.     static u_short execport = 0;
  633.  
  634.     if (!execport) {
  635.         if (!(se = getservbyname("exec", "tcp"))) {
  636.             pvmlogprintf("phase1() can't getservbyname(): %s\n", "exec");
  637.             pvmbailout(0);
  638.         }
  639.         execport = se->s_port;
  640.         endservent();
  641.     }
  642. #endif
  643.  
  644.     hp = sp->s_hst;
  645.     hn = hp->h_name;
  646.     sp->s_rfd = sp->s_wfd = sp->s_efd = -1;
  647.  
  648.     /*
  649.     * XXX manual startup hack... this is if we can't use rexec or rsh
  650.     */
  651.  
  652.     if (hp->h_flag & HST_MANUAL) {
  653.         fprintf(stderr, "*** Manual startup ***\n");
  654.         fprintf(stderr, "Login to \"%s\" and type:\n", hn);
  655.         fprintf(stderr, "%s\n", hp->h_cmd);
  656.  
  657.     /* get version */
  658.  
  659.         fprintf(stderr, "Type response: ");
  660.         fflush(stderr);
  661.         if (!(fgets(buf, sizeof(buf), stdin))) {
  662.             pvmlogprintf("host %s read error\n", hn);
  663.             goto oops;
  664.         }
  665.         p = buf + strlen(buf) - 1;
  666.         if (*p == '\n')
  667.             *p = 0;
  668.         hp->h_result = STRALLOC(buf);
  669.         fprintf(stderr, "Thanks\n");
  670.         fflush(stderr);
  671.         return 0;
  672.     }
  673.  
  674.     /*
  675.     * XXX end manual startup hack
  676.     */
  677.  
  678.     if (!(hp->h_flag & HST_PASSWORD)) {        /* use rsh to start */
  679.         int wpfd[2], rpfd[2], epfd[2];
  680.         int i;
  681.  
  682.         if (pvmdebmask & PDMSTARTUP) {
  683.             pvmlogprintf("phase1() trying rsh to %s\n", hn);
  684.         }
  685.  
  686.     /* fork an rsh to startup the slave pvmd */
  687.  
  688. #ifdef    IMA_TITN
  689.         if (socketpair(AF_UNIX, SOCK_STREAM, 0, wpfd) == -1
  690.         || socketpair(AF_UNIX, SOCK_STREAM, 0, rpfd) == -1
  691.         || socketpair(AF_UNIX, SOCK_STREAM, 0, epfd) == -1) {
  692.             pvmlogperror("phase1() socketpair");
  693.             goto oops;
  694.         }
  695. #else
  696.         if (pipe(wpfd) == -1 || pipe(rpfd) == -1 || pipe(epfd) == -1) {
  697.             pvmlogperror("phase1() pipe");
  698.             goto oops;
  699.         }
  700. #endif
  701.  
  702.         if (pvmdebmask & PDMSTARTUP) {
  703.             pvmlogprintf("phase1() pipes: %d %d %d %d %d %d\n",
  704.                     wpfd[0], wpfd[1], rpfd[0], rpfd[1], epfd[0], epfd[1]);
  705.         }
  706.  
  707.         if ((pid = fork()) == -1) {
  708.             pvmlogperror("phase1() fork");
  709.             pvmbailout(0);
  710.         }
  711.         if (!pid) {
  712.             (void)dup2(wpfd[0], 0);
  713.             (void)dup2(rpfd[1], 1);
  714.             (void)dup2(epfd[1], 2);
  715.             for (i = getdtablesize(); --i > 2; )
  716.                 (void)close(i);
  717.             ac = 0;
  718.             av[ac++] = RSHCOMMAND;
  719.             av[ac++] = hn;
  720.             if (hp->h_login) {
  721.                 av[ac++] = "-l";
  722.                 av[ac++] = hp->h_login;
  723.             }
  724.             av[ac++] = hp->h_cmd;
  725.             av[ac++] = 0;
  726.             if (pvmdebmask & PDMSTARTUP) {
  727.                 for (ac = 0; av[ac]; ac++)
  728.                     fprintf(stderr, "av[%d]=\"%s\" ", ac, av[ac]);
  729.                 fputc('\n', stderr);
  730.             }
  731.             execvp(av[0], av);
  732.             fputs("phase1() execvp failed\n", stderr);
  733.             fflush(stderr);
  734.             _exit(1);
  735.         }
  736.         (void)close(wpfd[0]);
  737.         (void)close(rpfd[1]);
  738.         (void)close(epfd[1]);
  739.         sp->s_wfd = wpfd[1];
  740.         sp->s_rfd = rpfd[0];
  741.         sp->s_efd = epfd[0];
  742.  
  743.     } else {        /* use rexec to start */
  744.  
  745. #ifdef NOREXEC
  746.         pvmlogprintf("slconfg() PVM was built without rexec support, can't take passwords\n");
  747.         goto oops;
  748. #else
  749.         if (pvmdebmask & PDMSTARTUP) {
  750.             pvmlogprintf("phase1() rexec \"%s\"\n", hp->h_cmd);
  751.         }
  752.         if ((sp->s_wfd = sp->s_rfd = rexec(&hn, execport,
  753.                 (hp->h_login ? hp->h_login : username),
  754.                 (char*)0, hp->h_cmd, &sp->s_efd))
  755.         == -1) {
  756.             pvmlogprintf("phase1() rexec failed for host %s\n", hn);
  757.             goto oops;
  758.         }
  759. #endif
  760.     }
  761.     return 0;
  762.  
  763. oops:
  764.     hp->h_result = STRALLOC("PvmCantStart");
  765.     if (sp->s_wfd != -1)
  766.         close(sp->s_wfd);
  767.     if (sp->s_rfd != -1)
  768.         close(sp->s_rfd);
  769.     if (sp->s_efd != -1)
  770.         close(sp->s_efd);
  771.     sp->s_wfd = sp->s_rfd = sp->s_efd = -1;
  772.     return 1;
  773. }
  774.  
  775.  
  776.